//--------------------------------------------------------------------------
// <copyright file="ParamAttribute.cs" company="Microsoft">
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// </copyright>
// <summary>ParamAttribute</summary>
//--------------------------------------------------------------------------
namespace MS.Msn.MediaSolutions.Common.Web
{
    using System;
    using System.Data;
    using System.Configuration;
    using System.Web;
    using System.Reflection;
    using System.ComponentModel;

    /// <summary>
    /// parameter attribute to get request
    /// </summary>
    [AttributeUsage(AttributeTargets.Field | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
    public sealed class ParamAttribute : Attribute
    {
        #region properties

        private string _paramName = string.Empty;
        /// <summary>
        /// parameter name
        /// </summary>
        public string ParamName
        {
            get { return _paramName; }
        }

        private string defaultValue = string.Empty;
        /// <summary>
        /// default value
        /// </summary>
        public string DefaultValue
        {
            get { return defaultValue; }
            set { defaultValue = value; }
        }

        #endregion

        #region constructor

        /// <summary>
        /// parameter attribute constructor
        /// </summary>
        /// <param name="paramName">parameter name</param>
        public ParamAttribute(string paramName)
        {
            _paramName = (string.IsNullOrEmpty(paramName) ? string.Empty : paramName);
        }

        #endregion

        #region set parameters

        /// <summary>
        /// set values
        /// </summary>
        /// <param name="target">page instance</param>
        /// <param name="request">page request</param>
        public static void SetValues(object target, HttpRequest request)
        {
            if (target != null)
            {
                Type tp = target.GetType();
                MemberInfo[] members = tp.GetMembers(BindingFlags.Instance | BindingFlags.Public);
                foreach (MemberInfo member in members)
                {
                    if ((member is FieldInfo) || (member is PropertyInfo))
                    {
                        SetValue(member, target, request);
                    }
                }
            }
            else
            {
                throw new ArgumentNullException(Apps.GetArgNullExString("target"));
            }
        }

        /// <summary>
        /// set values
        /// </summary>
        /// <param name="member">member</param>
        /// <param name="target">target</param>
        /// <param name="request">request</param>
        public static void SetValue(MemberInfo member, object target, System.Web.HttpRequest request)
        {
            if (target != null)
            {
                if (member != null)
                {
                    object typedValue = null;
                    ParamAttribute[] attribs = (ParamAttribute[])member.GetCustomAttributes(typeof(ParamAttribute), true);

                    if (attribs != null && attribs.Length > 0)
                    {
                        if (member.MemberType == MemberTypes.Property)
                        {
                            ParameterInfo[] ps = ((PropertyInfo)member).GetIndexParameters();
                            if (!object.Equals(ps, null) && ps.Length > 0)
                            {
                                return;
                            }
                        }

                        ParamAttribute attrib = attribs[0];
                        string pName = string.IsNullOrEmpty(attrib.ParamName) ? member.Name : attrib.ParamName;
                        string pValue = string.Empty;

                        if (request != null)
                        {
                            pValue = request[pName];
                            if (object.Equals(pValue, null))
                            {
                                pValue = attrib.DefaultValue;
                            }
                        }

                        if (!string.IsNullOrEmpty(pValue))
                        {
                            try
                            {
                                TypeConverter converter = TypeDescriptor.GetConverter(GetMemberType(member));
                                if (object.Equals(converter, null) || !converter.CanConvertFrom(pValue.GetType()))
                                {
                                    throw new TypeLoadException(String.Format(Apps.DefaultCulture, "convert failed: {0}", pValue.GetType()));
                                }

                                typedValue = converter.ConvertFrom(pValue);
                                SetMemberValue(member, target, typedValue);
                            }
                            catch
                            {
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// get member type
        /// </summary>
        /// <param name="member">member</param>
        /// <returns>type</returns>
        private static Type GetMemberType(MemberInfo member)
        {
            switch (member.MemberType)
            {
                case MemberTypes.Field:
                    return ((FieldInfo)member).FieldType;
                case MemberTypes.Property:
                    return ((PropertyInfo)member).PropertyType;
                default:
                    return null;
            }
        }

        /// <summary>
        /// set Fields, set Properties
        /// </summary>
        /// <param name="member">member instance</param>
        /// <param name="target">field or property name</param>
        /// <param name="value">to value</param>
        private static void SetMemberValue(MemberInfo member, object target, object value)
        {
            switch (member.MemberType)
            {
                case MemberTypes.Field:
                    ((FieldInfo)member).SetValue(target, value);
                    break;
                case MemberTypes.Property:
                    ((PropertyInfo)member).SetValue(target, value, new Object[0]);
                    break;
            }
        }
        #endregion
    }
}
